<template>
  <q-scroll-area style="height: 300px;" class="q-px-md">
    <q-timeline :layout="layout" color="secondary">
      <div class="text-center text-h6 q-pb-md">变动历史</div>
      <q-separator />

      <q-timeline-entry
        v-for="(item, idx) in data"
        :Key="idx"
        :title="item.user + operate[item.operate].label"
        :subtitle="toDate(item.time)"
        :side="idx % 2 == 0 ? 'left' : 'right'"
        :icon="operate[item.operate].icon"
        :color="operate[item.operate].color"
      >
        <div v-if="item.operate === 'update'">
          <div v-for="(row, i) in item.change" :key="row.field + i">
            <div v-html="explain(row)"></div>
          </div>
        </div>
        <div v-else-if="item.operate === 'insert'">
          <div v-html="explain(item)"></div>
        </div>
        <div v-else-if="item.operate === 'delete'">
          <div v-html="explain(item)"></div>
        </div>
      </q-timeline-entry>
    </q-timeline>
  </q-scroll-area>
</template>
<script>
import { defineComponent } from 'vue';
import moment from 'moment';
import { mapState, mapActions } from 'pinia';
import { useStore } from 'stores/store';
import DOMPurify from 'dompurify';

export default defineComponent({
  name: 'history',
  props: {
    data: { // 数据
      type: Array,
      default: () => []
    },
    escape: { // 转义字段
      type: Object,
      default: () => {}
    },
    tableFields: { // 明细表
      type: Object,
      default: () => {}
    }
  },
  data () {
    return {
      operate: {
        create: {
          label: '创建记录',
          icon: 'add',
          color: 'blue'
        },
        update: {
          label: '修改记录',
          icon: 'edit',
          color: 'green'
        },
        insert: {
          label: '插入数据',
          icon: 'playlist_add',
          color: 'indigo'
        },
        delete: {
          label: '删除数据',
          icon: 'playlist_play',
          color: 'negative'
        }
      }
    };
  },
  methods: {
    toDate (timestamp) {
      return moment(timestamp, 'X').format('YYYY/MM/DD HH:mm');
    },
    explain (item) {
      if (!item.model) { // 主表
        let { oldValue, newValue } = item;
        if (this.escape[item.field]) { // 需要转义
          if (this.escape[item.field].type === 'date') {
            oldValue = oldValue && moment(oldValue, 'X').format('YYYY/MM/DD HH:mm');
            newValue = newValue && moment(newValue, 'X').format('YYYY/MM/DD HH:mm');
          } else if (this.escape[item.field].type === 'select') {
            if (this.escape[item.field].dict) {
              oldValue = oldValue && this.dictObj[this.escape[item.field].dict] && this.dictObj[this.escape[item.field].dict][oldValue] && this.dictObj[this.escape[item.field].dict][oldValue].label;
              newValue = newValue && this.dictObj[this.escape[item.field].dict] && this.dictObj[this.escape[item.field].dict][newValue] && this.dictObj[this.escape[item.field].dict][newValue].label;
            } else {
              const oldOpt = this.escape[item.field].options.find(i => i.value === oldValue);
              if (oldOpt) oldValue = oldOpt.label;
              const newOpt = this.escape[item.field].options.find(i => i.value === newValue);
              if (newOpt) newValue = newOpt.label;
            }
          } else if (this.escape[item.field].type === 'image') {
            oldValue = oldValue && oldValue.length > 0 ? oldValue.map(v => `<img src="${v.thumb}" style="max-width: 50px;max-height: 50px;" />`).join('') : '';
            newValue = newValue && newValue.length > 0 ? newValue.map(v => `<img src="${v.thumb}" style="max-width: 50px;max-height: 50px;" />`).join('') : '';
          } else if (this.escape[item.field].type === 'attach') {
            oldValue = oldValue && oldValue.length > 0 ? oldValue.map(v => `<a href="${v.url}" download="${v.filename}">[${v.filename}]</a>`).join('') : '';
            newValue = newValue && newValue.length > 0 ? newValue.map(v => `<a href="${v.url}" download="${v.filename}">[${v.filename}]</a>`).join('') : '';
          }
        } else if (item.field === 'approval_state') { // 审批状态特殊处理
          oldValue = oldValue && this.dictObj.approvalState && this.dictObj.approvalState[oldValue].label;
          newValue = newValue && this.dictObj.approvalState && this.dictObj.approvalState[newValue].label;
        } else if (item.field === 'approval_time') { // 审批时间特殊处理
          oldValue = oldValue && moment(oldValue, 'X').format('YYYY/MM/DD HH:mm');
          newValue = newValue && moment(newValue, 'X').format('YYYY/MM/DD HH:mm');
        }
        // 消毒html，防止xss攻击
        return DOMPurify.sanitize(`<div class="q-pa-sm">
          <div><span class="text-bold">${item.comment}</span> 的值</div>
          <div>从 <span class="text-green text-bold">${oldValue}</span></div>
          <div>改为 <span class="text-blue text-bold">${newValue}</span></div>
          </div>`);
      } else if (this.tableFields[item.model]) { // 从表
        const cols = this.tableFields[item.model].columns.filter(v => !!v.visible || v.visible === undefined);
        if (['insert', 'delete'].includes(item.operate)) {
          const chgItem = [];
          item.data.forEach(row => {
            cols.forEach(col => {
              let colVal = row[col.field];
              if (col.editConfig && col.editConfig.type === 'select' && col.editConfig.dict && this.dictObj[col.editConfig.dict]) {
                colVal = this.dictObj[col.editConfig.dict][colVal] && this.dictObj[col.editConfig.dict][colVal].label;
              }
              chgItem.push(`${col.label}:${colVal}`);
            });
          });
          return DOMPurify.sanitize(`<div class="q-pa-sm">
          <div><span class="text-bold">${this.tableFields[item.model].label}</span>${this.operate[item.operate].label}</div>
          <div>${chgItem.join(',')}</div>
          </div>`);
        }
      }
    }
  },
  computed: {
    ...mapState(useStore, ['dictObj']),
    layout () {
      return this.$q.screen.lt.sm ? 'dense' : (this.$q.screen.lt.md ? 'comfortable' : 'loose')
    }
  }
});
</script>
